package com.fishsticks.view;

import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

import com.fishsticks.R;
import com.fishsticks.model.DatabaseManager;
import com.fishsticks.model.ToDoItem;

import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Point;
import android.graphics.drawable.Drawable;
import android.location.Geocoder;
import android.location.LocationManager;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
import android.widget.ImageView;
import android.widget.RelativeLayout;


import android.os.Bundle;

import com.google.android.maps.GeoPoint;
import com.google.android.maps.ItemizedOverlay;
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapController;
import com.google.android.maps.MapView;
import com.google.android.maps.MyLocationOverlay;
import com.google.android.maps.Overlay;
import com.google.android.maps.OverlayItem;



public class MapsActivity extends MapActivity {

	private Menu menu;
	private Bundle extras;
	private DatabaseManager db;
	private String currentUser;
	private double latitude, longitude, oldLatitude, oldLongitude;
	private boolean showSingleToDo = false, showToDoList = true, singleToDoChanged = false;
	private ArrayList<ToDoItem> toDoList;
	private GeoPoint singleToDo;
	private MapView map;
	private MapController mapController;
	private LocationManager locationManager;
	private MyLocationOverlay locationOverlay;

	/**
     * Called when the activity is first 
     * created; Initializes map screen
     * and action bar buttons on top
     */
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        //this.requestWindowFeature(Window.FEATURE_NO_TITLE);
        this.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
        this.setContentView(R.layout.map_page);
        
        map = (MapView) findViewById(R.id.mapView);
        map.setBuiltInZoomControls(true);
        mapController = map.getController();
        mapController.setZoom(17);
        
        

        // Gets to-do item data from other activity
        extras = getIntent().getExtras();
        
        db = new DatabaseManager(this);
        currentUser = db.getLoggedInUser();

        //refreshes the list if a new to-do was added
        if(extras != null)
        {
        	//if coming from add-to-do page and only showing one to-do
        	if(extras.getBoolean("showSingleToDo")) {
	        	//get intent extra info from to-do item
	        	oldLatitude = Double.valueOf(extras.getString("latitudeNum"));
	        	oldLongitude = Double.valueOf(extras.getString("longitudeNum"));
	        	latitude = Double.valueOf(extras.getString("latitudeNum"));
	        	longitude = Double.valueOf(extras.getString("longitudeNum"));
	        	
	        	//so we know to show only one to-do or the whole list
	        	showSingleToDo = true;
	        	showToDoList = false;
        	}
        	else if(extras.getBoolean("showToDoList")) {
        		//so we know to show only one to-do or the whole list
	        	showSingleToDo = false;
	        	showToDoList = true;
        	}
        }

        
        if(showToDoList) {
        	toDoList = db.getToDoItems(db.getLoggedInUser());
        	
        	//Create geopoints and map pins for each todo item
        	for(int i=0; i<toDoList.size(); i++) {
        		map.getOverlays().add(new MapOverlay(toDoList.get(i).getLocation()));
        	}
        	
        	locationOverlay = new MyLocationOverlay(this, map);
        	map.getOverlays().add(locationOverlay);
        	mapController.animateTo(toDoList.get(0).getLocation());
        }
        
        else if(showSingleToDo) {
        	singleToDo = new GeoPoint(new Double(latitude*1000000).intValue(), new Double(longitude*1000000).intValue());
        	mapController.animateTo(singleToDo);
        	
        	//Drawable mapPin = getResources().getDrawable(R.drawable.places_icon);
        	//mapPin.setBounds(0, 0, mapPin.getIntrinsicWidth(), mapPin.getIntrinsicHeight());
        	map.getOverlays().add(new MapOverlay(singleToDo));
        	
        	locationOverlay = new MyLocationOverlay(this, map);
        	map.getOverlays().add(locationOverlay);
        }

        db.close();
    }


    
    
    
    public GeoPoint findMiddleGeoPoint(List<ToDoItem> toDoList) {
    	GeoPoint middlePoint = null, newPoint = null;
    	double midLat = 0.0, midLon = 0.0;
    	
    	for(int i=0; i<toDoList.size(); i++) {
    		
    		if(toDoList.size() > 2) {
	    		if(i < 2) {
	    			
	    			midLat = Math.abs((toDoList.get(1).getLatitude()/1000000)-(toDoList.get(0).getLatitude()/1000000))/2 + 
	    									Math.min((toDoList.get(0).getLatitude()/1000000), (toDoList.get(1).getLatitude()/1000000));
	    			midLon = Math.abs((toDoList.get(1).getLongitude()/1000000)-(toDoList.get(0).getLongitude()/1000000))/2 + 
	    									Math.min((toDoList.get(0).getLongitude()/1000000), (toDoList.get(1).getLongitude()/1000000));
	    		}
	    		else {
	    			midLat = (midLat + Math.abs((toDoList.get(i).getLatitude()/1000000)-midLat)/2 + 
	    									Math.min((toDoList.get(i).getLatitude()/1000000), midLat)) / 2;
	    			midLon = (midLon + Math.abs((toDoList.get(i).getLongitude()/1000000)-midLon)/2 + 
											Math.min((toDoList.get(i).getLongitude()/1000000), midLon)) / 2;
	    		}
    		}
    		
    		else if(toDoList.size() == 2) {
    			midLat = Math.abs((toDoList.get(1).getLatitude()/1000000)-(toDoList.get(0).getLatitude()/1000000))/2 + 
    										Math.min((toDoList.get(0).getLatitude()/1000000), (toDoList.get(1).getLatitude()/1000000));
    			midLon = Math.abs((toDoList.get(1).getLongitude()/1000000)-(toDoList.get(0).getLongitude()/1000000))/2 + 
    										Math.min((toDoList.get(0).getLongitude()/1000000), (toDoList.get(1).getLongitude()/1000000));
    		}
    		
    		else { //if size == 1
    			midLat = toDoList.get(0).getLatitude()/1000000;
    			midLon = toDoList.get(0).getLongitude()/1000000;
    		}
    	}
    	
    	return new GeoPoint((int)midLat*1000000, (int)midLon*1000000);
    }
    
    


    /**
     * Creates the menu options in the action bar at the top.
     */
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
    	this.menu = menu;
    	getMenuInflater().inflate(R.menu.map_menu, menu);
    	return true;
    }
    
    
    
    
    
    /**
     * Prepares options menu in the action bar at the top
     */
    @Override
    public boolean onPrepareOptionsMenu(Menu menu) {
    	this.menu = menu;
    	
    	//hides the check button at the top when 
    	// showing entire to do list pins on map
    	if(showToDoList) {
    		MenuItem acceptButton = menu.findItem(R.id.accept_new_map_point);
    		MenuItem cancelButton = menu.findItem(R.id.cancel_map_point);
    		
    		if(acceptButton != null) {
    			acceptButton.setVisible(false);
    			acceptButton.setEnabled(false);
    		}
    		
    		if(cancelButton != null) {
    			cancelButton.setVisible(true);
    			cancelButton.setEnabled(true);
    		}
    	}
    	
    	else {
    		MenuItem acceptButton = menu.findItem(R.id.accept_new_map_point);
    		MenuItem cancelButton = menu.findItem(R.id.cancel_map_point);
    		
    		if(acceptButton != null) {
    			acceptButton.setVisible(true);
    			acceptButton.setEnabled(true);
    		}
    		
    		if(cancelButton != null) {
    			cancelButton.setVisible(true);
    			cancelButton.setEnabled(true);
    		}
    	}
    	
    	return true;
    }



    

    /**
     * Listeners for the top bar menu items
     */
    @Override
    public boolean onOptionsItemSelected(MenuItem item)
    {
    	final Intent i = new Intent(this, ToDoListActivity.class);
    	i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
    	
    	final Intent backFromMapViewIntent = new Intent(this, ToDoListActivity.class);
    	//backFromMapViewIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
    	
    	final Intent acceptIntent = new Intent(this, AddNewToDoActivity.class);
    	acceptIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); /*| Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);*/
    	

    	switch(item.getItemId())
        {
        	//When the user clicks the top-left home icon
            case android.R.id.home:
                startActivity(i);
                finish();
            	return true;
            	
            	
            //sends new location data to add-to-do page
            case R.id.accept_new_map_point:
            	if(showSingleToDo) {
	            	acceptIntent.putExtra("locationChanged", singleToDoChanged);
	            	if(getParent() != null)
	            		getParent().setResult(1, acceptIntent);
	            	else
	            		setResult(1, acceptIntent);
	            	acceptIntent.putExtra("newLatitude", new Double(singleToDo.getLatitudeE6()/1000000.0).doubleValue());
	            	acceptIntent.putExtra("newLongitude", new Double(singleToDo.getLongitudeE6()/1000000.0).doubleValue());
	            	finish();
            	}
            	return true;
            	
            	
            //cancels map page and goes back to add to-do page
            case R.id.cancel_map_point:
            	if(showSingleToDo) {
            		if(getParent() != null)
	            		getParent().setResult(2, acceptIntent);
	            	else
	            		setResult(2, acceptIntent);
            		acceptIntent.putExtra("locationChanged", false);
	            	acceptIntent.putExtra("oldLatitude", oldLatitude);
	            	acceptIntent.putExtra("oldLongitude", oldLongitude);
            	}
            	finish();
            	return true;

      
            	
            default:
                return super.onOptionsItemSelected(item);
        }
    }






    /**
     * Generic map method that needs to be overridden so
     *   the map doesn't think it needs to show a 'route'
     */
	@Override
	protected boolean isRouteDisplayed() {
		// TODO Auto-generated method stub
		return false;
	}







	
	
	/**
	 * Helper class representing a pin on the map
	 */
	private class MapOverlay extends Overlay 
	{
		private GeoPoint point;
		
		public MapOverlay(GeoPoint p) {
			point = p;
		}
		
		@Override
	    public boolean draw(Canvas canvas, MapView mapView, boolean shadow, long when) 
	    {
	        super.draw(canvas, mapView, shadow);                   

	        //get GeoPoint into pixel data
	        Point screenPts = new Point();
	        mapView.getProjection().toPixels(point, screenPts);

	        // add the marker onto the map
	        Bitmap bmp = BitmapFactory.decodeResource(getResources(), R.drawable.places_icon);  
	        canvas.drawBitmap(bmp, screenPts.x-46, screenPts.y-96, null);         
	        return true;
	    }
		
		
		
		//Moves pointer location around when you tap 
		//(only if one single location is being shown)
		@Override 
		public boolean onTap(GeoPoint newPoint, MapView mapView) {
			if(showSingleToDo && !showToDoList) {
				singleToDoChanged = true;
				singleToDo = newPoint;
				point = newPoint;
				Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.places_icon);
				mapView.postInvalidate();
			}
			return true;
		}
		
		
		/*
		private List<OverlayItem> items = new ArrayList<OverlayItem>();
	    private Drawable image = null;
	    private OverlayItem inDrag = null;
	    private ImageView dragImage = null;
	    private int xDragImageOffset = 0, yDragImageOffset = 0, xDragTouchOffset = 0, yDragTouchOffset = 0;
	    
	    public MapOverlay(Drawable img) {
	    	super(img);
	    	this.image=img;
	      
	    	dragImage=(ImageView)findViewById(R.id.map_drag_image);
	    	xDragImageOffset=dragImage.getDrawable().getIntrinsicWidth()/2;
	    	yDragImageOffset=dragImage.getDrawable().getIntrinsicHeight();
	
	    	populate();
	    }
	    
	    
	    
	    @Override
	    protected OverlayItem createItem(int i) {
	    	return(items.get(i));
	    }
	    
	    
	    
	    @Override
	    public void draw(Canvas canvas, MapView mapView, boolean shadow) {
	    	super.draw(canvas, mapView, shadow);
	    	boundCenterBottom(image);
	    }
	    
	    
	    
	    
	    @Override
	    public int size() {
	    	return(items.size());
	    }
	    
	    
	    
	    
	    
	    @Override
	    public boolean onTouchEvent(MotionEvent event, MapView mapView) 
	    {
	    	final int action=event.getAction();
	    	final int x=(int)event.getX();
	    	final int y=(int)event.getY();
	    	boolean result=false;
	      
	    	if (action==MotionEvent.ACTION_DOWN) 
	    	{
	    		for (OverlayItem item : items) 
	    		{
	    			Point p=new Point(0,0);
	          
	    			map.getProjection().toPixels(item.getPoint(), p);
	          
	    			if (hitTest(item, image, x-p.x, y-p.y)) 
	    			{
	    				result=true;
	    				inDrag=item;
	    				items.remove(inDrag);
	    				populate();
	
	    				xDragTouchOffset=0;
	    				yDragTouchOffset=0;
	            	
			            setDragImagePosition(p.x, p.y);
			            dragImage.setVisibility(View.VISIBLE);
			
			            xDragTouchOffset=x-p.x;
			            yDragTouchOffset=y-p.y;
			            
			            break;
	    			}
	    		}
	    	}
	    	
	    	else if (action == MotionEvent.ACTION_MOVE && inDrag != null) 
	    	{
		        setDragImagePosition(x, y);
		        result=true;
	    	}
	    	
	    	else if (action == MotionEvent.ACTION_UP && inDrag != null) 
	    	{
		        dragImage.setVisibility(View.GONE);
		        
		        GeoPoint pt=map.getProjection().fromPixels(x-xDragTouchOffset, y-yDragTouchOffset);
		        OverlayItem toDrop=new OverlayItem(pt, inDrag.getTitle(), inDrag.getSnippet());
		        
		        items.add(toDrop);
		        populate();
		        
		        inDrag = null;
		        result = true;
	    	}
	      
	    	return(result || super.onTouchEvent(event, mapView));
	    }
	    
	    
	    
	    private void setDragImagePosition(int x, int y) {
	    	RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams)dragImage.getLayoutParams();
	            
	    	lp.setMargins(x-xDragImageOffset-xDragTouchOffset, y-yDragImageOffset-yDragTouchOffset, 0, 0);
	    	
	    	dragImage.setLayoutParams(lp);
	    }*/
	}	
}